## /*******************************************/
## /******* 交易策略-回测与经典策略（低买高卖）*******/
## /*******************************************/
import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

data = ak.stock_zh_a_hist(symbol="601318", start_date="20250101", end_date="20250301")

print(data.head())

# 根据data创建一个新的数据表
data_signal = pd.DataFrame(index=data.index)
data_signal['日期'] = data['日期']
data_signal['价格'] = data['收盘']
data_signal['涨跌额'] = data['涨跌额']
#创建交易信号字段，命名为“标记”
#如果涨跌额值大于0，则“标记”为0，否则为1
data_signal['标记'] = np.where(data['涨跌额'] > 0, 0, 1)
# 根据交易信号变化进行下单
# 一般情况下，在A股市场，买入或卖出至少为100股，即1手
data_signal['订单'] = data_signal['标记'].diff()*100
# 检查下单情况
print(data_signal.head())

# 股票初始金额 2万元人民币
initial_cash = 20000
# 股票市值
data_signal['市值'] = data_signal['订单']*data_signal['价格']
# 持仓股票的数量变化乘以现价，就是交易产生的现金流
# 初始化资金减去现金流变化的累加，就是剩余现金
data_signal['现金'] = initial_cash - (data_signal['订单'].diff()*data_signal['价格']).cumsum()
# 股票的市值加上剩余现金，就是总资产
data_signal['资产'] = data_signal['市值'] + data_signal['现金']
# 图形化展示
plt.figure(figsize=(10,6))
# 绘制总资产和持仓股票市值的变化
plt.plot(data_signal['资产'])
plt.plot(data_signal['订单'].cumsum()*data_signal['价格'],'--',label='stock value')
# 增加网格，调整一下图注的位置
plt.grid()
plt.legend(loc='center right')
plt.show()

# 10日均线
period = 10
# 设置一个空列表，用来存储每10天的价格
avg_10 = []
# 再设置一个空列表，用来存储每10天价格的均值
avg_value = []
# 设置一个循环
for price in data_signal['价格']:
    # 把每天的价格传入avg_10
    avg_10.append(price)
    # 当列表中存储的值多于10个时
    if len(avg_10) > period:
        # 就把前面传入的价格数据删除，确保列表中最多只有10天的数据
        del avg_10[0]
    # 将10天的数据的均值传入avg_value列表中
    avg_value.append(np.mean(avg_10))
# 把计算好的10日均价写到股票价格数据表
data_signal = data_signal.assign(avg_10 = pd.Series(avg_value,index=data_signal.index))
print(data_signal.head())
# 股价与均价对比
plt.figure(figsize=(10,6))
# 绘制股价的变化
plt.plot(data_signal['价格'],lw=2, c='k', label='price')
# 绘制10日均线
plt.plot(data_signal['avg_10'], '--', lw=2, c='b', label='avg')
# 添加图注和网格
plt.legend()
plt.grid()
plt.show()

#双移动平均策略
strategy = pd.DataFrame(index=data.index)
strategy['日期'] = data['日期']
strategy['价格'] = data['收盘']
strategy['涨跌额'] = data['涨跌额']
#创建交易信号字段，命名为“标记”
strategy['标记'] = 0
# 5日均价
strategy['5日均价'] = data['收盘'].rolling(5).mean()
# 10日均价
strategy['10日均价'] = data['收盘'].rolling(10).mean()
# 当5日均价大于10日均价时，标记为1
# 反之标记为0
strategy['标记'] = np.where(strategy['5日均价'] > strategy['10日均价'],1,0)
# 根据交易信号下单
strategy['下单'] = strategy['标记'].diff()
# 查看数据表后10 行
print(strategy.tail(10))
# 绘图
plt.figure(figsize=(10,5))
# 设置中文字体
plt.rcParams['font.family'] = 'SimHei'  # 替换为你选择的字体
# 使用实线绘制股价
plt.plot(strategy['价格'],lw=2, c='k', label='价格')
# 绘制5日均线虚线
plt.plot(strategy['5日均价'], ls='--', lw=2, label='5日均线')
# 绘制10日均线-.
plt.plot(strategy['10日均价'], ls='-.', lw=2, label='10日均线')
# 将买入信号用正三角进行标记
plt.scatter(strategy.loc[strategy['下单']==1].index, strategy['价格'][strategy['下单']==1], marker='^', s=80, color='r',label='买入')
# 将卖出信号用倒三角进行标记
plt.scatter(strategy.loc[strategy['下单']==-1].index, strategy['价格'][strategy['下单']==-1], marker='v', s=80, color='g',label='卖出')
plt.legend()
plt.grid()
plt.show()
